using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.HomeServer.SDK.Interop.v1;
using System.IO;
using System.Runtime.InteropServices;

namespace WhsFacebook.Whs
{
    public sealed class ApplicationFolders
    {
        public static readonly string HomeServerDir = (Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\Windows Home Server");
        public static readonly string WindowsSystem32 = Environment.GetFolderPath(Environment.SpecialFolder.System);

        // keep in sync with:
        // log4net.config: file value
        // *.wxs WhsFacebookAppFolderNonDup and WhsFacebookAppFolderDup properties
        public static readonly Guid NonDuplicatedId = new Guid("a5dc1c1d-e9fa-4cec-894c-3b21559ec000" /*msi product id*/);
        public static readonly Guid DuplicatedId = new Guid("a5dc1c1d-e9fa-4cec-894c-3b21559ec001" /*msi product id+1*/);

        private static object _instanceCreateLock = new object();
        private static volatile ApplicationFolders _instance = null;

        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(ApplicationFolders));
        private WHSInfoClass _whs;
        private object _nonDuplicatedCreateLock = new object();
        private object _duplicatedCreateLock = new object();

        public static ApplicationFolders Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_instanceCreateLock)
                    {
                        if (_instance == null)
                        {
                            _instance = new ApplicationFolders();
                        }
                    }
                }

                return _instance;
            }
        }

        public IApplicationFolder NonDuplicated
        {
            get
            {
                try
                {
                    var f = GetApplicationFolderSafe(NonDuplicatedId);
	
                    if (f == null)
                    {
                        lock (_nonDuplicatedCreateLock)
                        {
                            _log.InfoFormat(
                                "Creating application folder: {1} ({0})",
                                NonDuplicatedId,
                                Properties.Constants.ApplicationFolderNonDuplicated
                                );

                            f = GetApplicationFolderSafe(NonDuplicatedId);
	
                            if (f == null)
                            {
                                f = _whs.CreateApplicationFolder(NonDuplicatedId, Properties.Constants.ApplicationFolderNonDuplicated);
	
                                f.IsDuplicated = 0;
                            }
                        }
                    }
	
                    return f;
                }
                catch (Exception e)
                {
                    _log.Fatal("Failed to get non-duplicated application folder: " + NonDuplicatedId.ToString(), e);

                    throw;
                }
            }
        }

        public DirectoryInfo NonDuplicatedDir
        {
            get { return new DirectoryInfo(this.NonDuplicated.Path); }
        }

        public IApplicationFolder Duplicated
        {
            get
            {
                try
                {
                    var f = GetApplicationFolderSafe(DuplicatedId);
	
                    if (f == null)
                    {
                        lock (_duplicatedCreateLock)
                        {
                            _log.InfoFormat(
                                "Creating application folder: {1} ({0})",
                                DuplicatedId,
                                Properties.Constants.ApplicationFolderDuplicated
                                );

                            f = GetApplicationFolderSafe(DuplicatedId);
	
                            if (f == null)
                            {
                                f = _whs.CreateApplicationFolder(DuplicatedId, Properties.Constants.ApplicationFolderDuplicated);
	
                                // TODO: wait for MS to implement duplication on app folders
                                try
                                {
                                    f.IsDuplicated = 1;
                                }
                                catch (NotImplementedException e)
                                {
                                    _log.Warn("Folder duplication still unsupported for application folders: " + DuplicatedId.ToString(), e);
                                }
                            }
                        }
                    }
	
                    return f;
                }
                catch (Exception e)
                {
                    _log.Fatal("Failed to get duplicated application folder: " + DuplicatedId.ToString(), e);

                    throw;
                }
            }
        }

        public DirectoryInfo DuplicatedDir
        {
            get { return new DirectoryInfo(this.Duplicated.Path); }
        }

        private IApplicationFolder GetApplicationFolderSafe(Guid id)
        {
            try
            {
                return _whs.GetApplicationFolder(id);
            }
            catch (COMException e)
            {
                if ((uint)e.ErrorCode == 0x80070490 /*not found*/)
                    return null;

                throw;
            }
        }

        private ApplicationFolders()
        {
            if (_log.IsDebugEnabled)
                _log.Debug("Creating singleton");

            try
            {
                _whs = new WHSInfoClass();
	
                _whs.Init(Properties.Constants.ApplicationName);
            }
            catch (Exception e)
            {
                _log.Fatal("Failed to create singleton", e);

                throw;
            }
        }


    }
}